home *** CD-ROM | disk | FTP | other *** search
- /***
- *
- * Copyright (c) 1998, Valve LLC. All rights reserved.
- *
- * This product contains software technology licensed from Id
- * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
- * All Rights Reserved.
- *
- ****/
-
- #include "qlumpy.h"
- #include "math.h"
-
- #pragma warning (disable : 4244)
-
- typedef struct
- {
- short ofs, length;
- } row_t;
-
- typedef struct
- {
- int width, height;
- int widthbits, heightbits;
- unsigned char data[4];
- } qtex_t;
-
- typedef struct
- {
- int width, height;
- byte data[4]; // variably sized
- } qpic_t;
-
-
- // Font stuff
-
- #define NUM_GLYPHS 256
- const unsigned kFontMarker = 254;
-
- typedef struct
- {
- short startoffset;
- short charwidth;
- } charinfo;
-
- typedef struct
- {
- int width, height;
- int rowcount;
- int rowheight;
- charinfo fontinfo[ NUM_GLYPHS ];
- byte data[4];
- } qfont_t;
-
-
- extern qboolean fTransparent255;
-
-
- #define SCRN(x,y) (*(byteimage+(y)*byteimagewidth+x))
-
- void GrabPalette16( void );
-
- extern qboolean do16bit;
-
- /*
- ==============
- GrabRaw
-
- filename RAW x y width height
- ==============
- */
- void GrabRaw (void)
- {
- int x,y,xl,yl,xh,yh,w,h;
- byte *screen_p;
- int linedelta;
-
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- w = atoi (token);
- GetToken (false);
- h = atoi (token);
-
- if (xl == -1)
- {
- xl = yl = 0;
- w = byteimagewidth;
- h = byteimageheight;
- }
-
- xh = xl+w;
- yh = yl+h;
-
- screen_p = byteimage + yl*byteimagewidth + xl;
- linedelta = byteimagewidth - w;
-
- for (y=yl ; y<yh ; y++)
- {
- for (x=xl ; x<xh ; x++)
- {
- *lump_p++ = *screen_p;
- *screen_p++ = 0;
- }
- screen_p += linedelta;
- }
- }
-
-
-
- /*
- ==============
- GrabPalette
-
- filename PALETTE [startcolor endcolor]
- ==============
- */
- void GrabPalette (void)
- {
- int start, end, length;
-
- if (TokenAvailable())
- {
- GetToken (false);
- start = atoi (token);
- GetToken (false);
- end = atoi (token);
- }
- else
- {
- start = 0;
- end = 255;
- }
-
- length = 3*(end-start+1);
- memcpy (lump_p, lbmpalette+start*3, length);
- lump_p += length;
- }
-
-
- /*
- ==============
- GrabPic
-
- filename qpic x y width height
- ==============
- */
- void GrabPic (void)
- {
- int x,y,xl,yl,xh,yh;
- int width;
- qpic_t *header;
-
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- xh = xl+atoi (token);
- GetToken (false);
- yh = yl+atoi (token);
-
- if (xl == -1)
- {
- xl = yl = 0;
- xh = byteimagewidth;
- yh = byteimageheight;
- }
-
- if (xh<xl || yh<yl || xl < 0 || yl<0) // || xh>319 || yh>239)
- Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,xh,yh);
-
- //
- // fill in header
- //
- header = (qpic_t *)lump_p;
- width = xh-xl;
- header->width = LittleLong(width);
- header->height = LittleLong(yh-yl);
-
- //
- // start grabbing posts
- //
- lump_p = (byte *)header->data;
-
- for (y=yl ; y< yh ; y++)
- for (x=xl ; x<xh ; x++)
- *lump_p++ = SCRN(x,y);
-
- // New for 16bpp display
- if( do16bit )
- GrabPalette16();
- }
-
- /*
- =============================================================================
-
- COLORMAP GRABBING
-
- =============================================================================
- */
-
- /*
- ===============
- BestColor
- ===============
- */
- byte BestColor (int r, int g, int b, int start, int stop)
- {
- int i;
- int dr, dg, db;
- int bestdistortion, distortion;
- int bestcolor;
- byte *pal;
-
- //
- // let any color go to 0 as a last resort
- //
- bestdistortion = ( (int)r*r + (int)g*g + (int)b*b )*2;
- bestcolor = 0;
-
- pal = lbmpalette + start*3;
- for (i=start ; i<= stop ; i++)
- {
- dr = r - (int)pal[0];
- dg = g - (int)pal[1];
- db = b - (int)pal[2];
- pal += 3;
- distortion = dr*dr + dg*dg + db*db;
- if (distortion < bestdistortion)
- {
- if (!distortion)
- return i; // perfect match
-
- bestdistortion = distortion;
- bestcolor = i;
- }
- }
-
- return bestcolor;
- }
-
-
- /*
- ==============
- GrabColormap
-
- filename COLORMAP levels fullbrights
- the first map is an identiy 0-255
- the final map is all black except for the fullbrights
- the remaining maps are evenly spread
- fullbright colors start at the top of the palette.
- ==============
- */
- void GrabColormap (void)
- {
- int levels, brights;
- int l, c;
- float frac, red, green, blue;
-
- GetToken (false);
- levels = atoi (token);
- GetToken (false);
- brights = atoi (token);
-
- // identity lump
- for (l=0 ; l<256 ; l++)
- *lump_p++ = l;
-
- // shaded levels
- for (l=1;l<levels;l++)
- {
- frac = 1.0 - (float)l/(levels-1);
- for (c=0 ; c<256-brights ; c++)
- {
- red = lbmpalette[c*3];
- green = lbmpalette[c*3+1];
- blue = lbmpalette[c*3+2];
-
- red = (int)(red*frac+0.5);
- green = (int)(green*frac+0.5);
- blue = (int)(blue*frac+0.5);
-
- //
- // note: 254 instead of 255 because 255 is the transparent color, and we
- // don't want anything remapping to that
- //
- *lump_p++ = BestColor(red,green,blue, 0, 254);
- }
- for ( ; c<256 ; c++)
- *lump_p++ = c;
- }
-
- *lump_p++ = brights;
- }
-
- /*
- ==============
- GrabColormap2
-
- experimental -- not used by quake
-
- filename COLORMAP2 range levels fullbrights
- fullbright colors start at the top of the palette.
- Range can be greater than 1 to allow overbright color tables.
-
- the first map is all 0
- the last (levels-1) map is at range
- ==============
- */
- void GrabColormap2 (void)
- {
- int levels, brights;
- int l, c;
- float frac, red, green, blue;
- float range;
-
- GetToken (false);
- range = atof (token);
- GetToken (false);
- levels = atoi (token);
- GetToken (false);
- brights = atoi (token);
-
- // shaded levels
- for (l=0;l<levels;l++)
- {
- frac = range - range*(float)l/(levels-1);
- for (c=0 ; c<256-brights ; c++)
- {
- red = lbmpalette[c*3];
- green = lbmpalette[c*3+1];
- blue = lbmpalette[c*3+2];
-
- red = (int)(red*frac+0.5);
- green = (int)(green*frac+0.5);
- blue = (int)(blue*frac+0.5);
-
- //
- // note: 254 instead of 255 because 255 is the transparent color, and we
- // don't want anything remapping to that
- //
- *lump_p++ = BestColor(red,green,blue, 0, 254);
- }
-
- // fullbrights allways stay the same
- for ( ; c<256 ; c++)
- *lump_p++ = c;
- }
-
- *lump_p++ = brights;
- }
-
- /*
- =============================================================================
-
- MIPTEX GRABBING
-
- =============================================================================
- */
-
- typedef struct
- {
- char name[16];
- unsigned width, height;
- unsigned offsets[4]; // four mip maps stored
- } miptex_t;
-
- byte pixdata[256];
-
- float linearpalette[256][3];
- float d_red, d_green, d_blue;
- int colors_used;
- int color_used[256];
- float maxdistortion;
-
- byte AddColor( float r, float g, float b )
- {
- int i;
- for (i = 0; i < 255; i++)
- {
- if (!color_used[i])
- {
- linearpalette[i][0] = r;
- linearpalette[i][1] = g;
- linearpalette[i][2] = b;
- if (r < 0) r = 0.0;
- if (r > 1.0) r = 1.0;
- lbmpalette[i*3+0] = pow( r, 1.0 / 2.2) * 255;
- if (g < 0) g = 0.0;
- if (g > 1.0) g = 1.0;
- lbmpalette[i*3+1] = pow( g, 1.0 / 2.2) * 255;
- if (b < 0) b = 0.0;
- if (b > 1.0) b = 1.0;
- lbmpalette[i*3+2] = pow( b, 1.0 / 2.2) * 255;
- color_used[i] = 1;
- colors_used++;
- return i;
- }
- }
- return 0;
- }
-
- /*
- =============
- AveragePixels
- =============
- */
- byte AveragePixels (int count)
- {
- float r,g,b;
- int i;
- int vis;
- int pix;
- float dr, dg, db;
- float bestdistortion, distortion;
- int bestcolor;
- byte *pal;
-
- vis = 0;
- r = g = b = 0;
-
- for (i=0 ; i<count ; i++)
- {
- pix = pixdata[i];
- r += linearpalette[pix][0];
- g += linearpalette[pix][1];
- b += linearpalette[pix][2];
- }
-
- r /= count;
- g /= count;
- b /= count;
-
- r += d_red;
- g += d_green;
- b += d_blue;
-
- //
- // find the best color
- //
- // bestdistortion = r*r + g*g + b*b;
- bestdistortion = 3.0;
- bestcolor = -1;
-
- for ( i=0; i<255; i++)
- {
- if (color_used[i])
- {
- pix = i; //pixdata[i];
-
- dr = r - linearpalette[i][0];
- dg = g - linearpalette[i][1];
- db = b - linearpalette[i][2];
-
- distortion = dr*dr + dg*dg + db*db;
- if (distortion < bestdistortion)
- {
- if (!distortion)
- {
- d_red = d_green = d_blue = 0; // no distortion yet
- return pix; // perfect match
- }
-
- bestdistortion = distortion;
- bestcolor = pix;
- }
- }
- }
-
-
- if (bestdistortion > 0.001 && colors_used < 255)
- {
- // printf("%f %f %f\n", r, g, b );
- bestcolor = AddColor( r, g, b );
- d_red = d_green = d_blue = 0;
- bestdistortion = 0;
- }
- else
- {
- // error diffusion
- d_red = r - linearpalette[bestcolor][0];
- d_green = g - linearpalette[bestcolor][1];
- d_blue = b - linearpalette[bestcolor][2];
- }
-
- if (bestdistortion > maxdistortion)
- maxdistortion = bestdistortion;
- return bestcolor;
- }
-
-
- /*
- ==============
- GrabMip
-
- filename MIP x y width height
- must be multiples of sixteen
- ==============
- */
- void GrabMip (void)
- {
- int i,j,x,y,xl,yl,xh,yh,w,h;
- byte *screen_p, *source, testpixel;
- int linedelta;
- miptex_t *qtex;
- int miplevel, mipstep;
- int xx, yy, pix;
- int count;
-
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- w = atoi (token);
- GetToken (false);
- h = atoi (token);
-
- if (xl == -1)
- {
- xl = yl = 0;
- w = byteimagewidth;
- h = byteimageheight;
- }
-
- if ( (w & 15) || (h & 15) )
- Error ("line %i: miptex sizes must be multiples of 16", scriptline);
-
- xh = xl+w;
- yh = yl+h;
-
- qtex = (miptex_t *)lump_p;
- qtex->width = LittleLong(w);
- qtex->height = LittleLong(h);
- strcpy (qtex->name, lumpname);
-
- lump_p = (byte *)&qtex->offsets[4];
-
- screen_p = byteimage + yl*byteimagewidth + xl;
- linedelta = byteimagewidth - w;
-
- source = lump_p;
- qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
-
- for (y=yl ; y<yh ; y++)
- {
- for (x=xl ; x<xh ; x++)
- {
- pix = *screen_p;
- *screen_p++ = 0;
- // if (pix == 255)
- // pix = 0;
- *lump_p++ = pix;
- }
- screen_p += linedelta;
- }
-
- // calculate gamma corrected linear palette
- for (i = 0; i < 256; i++)
- {
- for (j = 0; j < 3; j++)
- {
- float f;
- f = lbmpalette[i*3+j] / 255.0;
- linearpalette[i][j] = pow(f, 2.2 ); // assume textures are done at 2.2, we want to remap them at 1.0
- }
- }
-
- maxdistortion = 0;
- if (!fTransparent255)
- {
- // figure out what palette entries are actually used
- colors_used = 0;
- for (i = 0; i < 256; i++)
- color_used[i] = 0;
-
- for (x = 0; x < w; x++)
- {
- for (y = 0; y < h; y++)
- {
- if (!color_used[source[ y*w + x]])
- {
- color_used[source[ y*w + x]] = 1;
- colors_used++;
- }
- }
- }
- }
- else
- {
- // assume palette full if it's a transparent texture
- colors_used = 256;
- for (i = 0; i < 256; i++)
- color_used[i] = 1;
- }
- // printf("colors_used %d : ", colors_used );
-
-
- //
- // subsample for greater mip levels
- //
-
- for (miplevel = 1 ; miplevel<4 ; miplevel++)
- {
- int pixTest;
- d_red = d_green = d_blue = 0; // no distortion yet
- qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
-
- mipstep = 1<<miplevel;
- pixTest = (int)( (float)(mipstep * mipstep) * 0.4 ); // 40% of pixels
-
- for (y=0 ; y<h ; y+=mipstep)
- {
- for (x = 0 ; x<w ; x+= mipstep)
- {
- count = 0;
- for (yy=0 ; yy<mipstep ; yy++)
- for (xx=0 ; xx<mipstep ; xx++)
- {
- testpixel = source[ (y+yy)*w + x + xx ];
-
- // If 255 is not transparent, or this isn't a transparent pixel, add it in to the image filter
- if ( !fTransparent255 || testpixel != 255 ) {
- pixdata[count] = testpixel;
- count++;
- }
- }
- if ( count <= pixTest ) // Solid pixels account for < 40% of this pixel, make it transparent
- {
- *lump_p++ = 255;
- }
- else
- {
- *lump_p++ = AveragePixels (count);
- }
- }
- }
- }
-
- // printf(" %d %f\n", colors_used, maxdistortion );
-
- if( do16bit )
- GrabPalette16();
- }
-
-
- /*
- =============================================================================
-
- PALETTE GRABBING
-
- =============================================================================
- */
-
-
- void GrabPalette16( void )
- {
- int i;
-
- // Write out palette in 16bit mode
- *(unsigned short *) lump_p = 256; // palette size
- lump_p += sizeof(short);
-
- memcpy( lump_p, lbmpalette, 768 );
- lump_p += 768;
- }
-
-
-
- /*
- =============================================================================
-
- FONT GRABBING
-
- =============================================================================
- */
-
-
- /*
- ==============
- GrabFont
-
- font x y width height startglyph
- ==============
- */
- void GrabFont( void )
- {
- int x, y, y2, xl, x2, yl, xh, yh, i, j;
- int index, offset;
- int width;
- int iCurX; // current x in destination
- int iMaxX; // max x in destination
-
- byte *pbuf, *pCur;
- qfont_t *header;
-
-
- iMaxX = 255;
- iCurX = 0;
-
- // Set up header
- header = (qfont_t *)lump_p;
- memset( header, 0, sizeof(qfont_t) );
-
- GetToken( false );
- header->width = header->rowheight = atoi( token ); //mwh why does width equal rowheight?
- header->height = 1;
- lump_p = (byte *)header->data;
- pCur = (byte *)lump_p;
- memset( lump_p, 0xFF, 256 * 160);
-
- GetToken( false );
- index = atoi( token );
-
- while( index != -1 )
- {
- // Get/Process source bitmap coordinates
- GetToken (false);
- xl = atoi (token);
- GetToken (false);
- yl = atoi (token);
- GetToken (false);
- xh = xl-1+atoi (token);
- GetToken (false);
- yh = atoi (token) - 1;
- if (xl == -1)
- {
- xl = yl = 0;
- xh = byteimagewidth;
- yh = byteimageheight;
- }
-
- if( xh<xl || yh<yl || xl < 0 || yl<0 )
- Error( "GrabFont line %1: Bad size: %i, %i, %i, %i", scriptline, xl, yl, xh, yh );
-
- //
- // Fill in font information
- // Create a bitmap that is up to 256 wide and as tall as we need to accomadate the font.
- // We limit the bitmap to 256 because some 3d boards have problems with textures bigger
- // than that.
- //
- for( y=yl; y<yh; y+=header->rowheight+1 )
- {
- // Make sure we're at a marker
- if( y != yl )
- {
- for( y2=y-header->rowheight; y2<yh; y2++ )
- if( kFontMarker == (unsigned) SCRN(xl,y2) )
- break;
-
- if( y2 == yh )
- break;
- else if( y2 != y )
- Error( "GrabFont line %d: rowheight doesn't seem to match bitmap (%d, %d)\n", scriptline, y, y2 );
- }
-
- for( x=xl; x<xh; )
- {
- // find next marker
- for( x2=x+1; x2<xh; x2++ )
- if( kFontMarker == (unsigned) SCRN(x2,y) )
- break;
-
- // check for end of row
- if( x2 == xh )
- break;
-
- // Set up glyph information
- if( index >= NUM_GLYPHS )
- {
- printf( "GrabFont: Glyph out of range\n" );
- goto getout;
- }
-
- // Fill in glyph info
- header->fontinfo[ index ].charwidth = x2 - x - 1;
-
- // update header
-
- // output glyph data
- iCurX += header->fontinfo[index].charwidth;
-
- // Will this glyph fit on this row?
- if (iCurX >= iMaxX)
- {
- // Nope -- move to next row
- pCur = (byte *)lump_p + 256 * header->rowheight * header->height;
- header->height++;
- iCurX = header->fontinfo[index].charwidth;
- }
-
- // copy over the glyph bytes
- pbuf = pCur;
- header->fontinfo[ index ].startoffset = pCur - (byte *) header->data;
-
-
- for(j = 1; j <= header->rowheight; j++)
- {
- byte *psrc = byteimage + (y + j) * byteimagewidth + (x + 1);
-
- for(i = x + 1; i < x2; i++)
- *pbuf++ = *psrc++;
-
- pbuf = pCur + j * 256;
- }
-
- // move the lump pointer to point at the next possible glyph
- pCur += header->fontinfo[index].charwidth;
- x = x2;
- index++;
- }
- }
-
- // Get next ASCII index
- getout:
- GetToken (false);
- index = atoi (token);
- }
-
- // advance the lump pointer so that the last row is saved.
- lump_p += (256 * header->rowheight) * header->height;
-
- // JAY: Round up to the next power of 2 for GL
- offset = header->height * header->rowheight;
-
- y = (offset>128)?256:(offset>64)?128:(offset>32)?64:(offset>16)?32:16;
- if ( offset != y )
- {
- printf("Rounding font from 256x%d to 256x%d\n", offset, y );
- lump_p += (256 * (y - offset));
- }
- header->rowcount = header->height;
- header->height = y;
-
- if( do16bit )
- GrabPalette16();
- }
-
-